/**
  * @desc authorise access token in request header
*/

const moment = require('moment')
const Role = require('../constant/Role')
const ResponseError = require('../helper/ResponseError')
const knexClient = require('../helper/knexClient')
const redisClient = require('../helper/redisClient')
const { AUTHENTICATION } = require('../constant/RedisKey')

const accessTokenTableName = 'access_token'

const authoriseToken = async (req, res, next) => {
  const bearerToken = req.headers.authorization || ''
  const bearerTokenParts = bearerToken.split(' ')
  const token = bearerTokenParts[0] === 'Bearer' && bearerTokenParts[1]
  if (token) {
    try {
      const redisKey = `${AUTHENTICATION}${token}`
      const redisResult = await redisClient.getRecord(redisKey)
      if (redisResult) {
        // `${ROLE}_${id}`
        const values = redisResult.split('_')
        const role = values[0]
        const accountId = values[1]
        req.context.role = role
        req.context.accountId = accountId
        if (process.env.NODE_ENV === 'development') {
          // console.log('AUTHORISE BY REDIS') // eslint-disable-line
        }
        return next()
      }
      const record = await knexClient.table(accessTokenTableName).where({ token }).first()
      // check if the token exists
      if (!record) {
        return next(new ResponseError.InvalidToken())
      }
      const {
        expired_at: expiredAt,
        administrator_id: administratorId,
        merchant_id: merchantId,
        user_id: userId,
      } = record
      // check token expiration
      const tokenExpiratedAt = moment.utc(expiredAt, 'YYYY-MM-DD HH:mm Z')
      if (moment().diff(tokenExpiratedAt) > 0) {
        return next(new ResponseError.ExpiredToken())
      }
      // set user id / role to req.context
      if (administratorId) {
        req.context.accountId = administratorId
        req.context.role = Role.ADMINISTRATOR
      } else if (merchantId) {
        req.context.accountId = merchantId
        req.context.role = Role.MERCHANT
      } else if (userId) {
        req.context.accountId = userId
        req.context.role = Role.USER
      }
      if (process.env.NODE_ENV === 'development') {
        // console.log('AUTHORISE BY DB') // eslint-disable-line
      }
      return next()
    } catch (error) {
      return next(error)
    }
  } else {
    return next()
  }
}

module.exports = authoriseToken
